#!/usr/bin/env python2.7
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Script to pull chromium.perf stats from chrome-infra-stats API.

Currently this just pulls success rates from the API, averages daily per
builder, and uploads to perf dashboard. It could be improved to provide more
detailed success rates.

The API documentation for chrome-infra-stats is at:
https://apis-explorer.appspot.com/apis-explorer/?
   base=https://chrome-infra-stats.appspot.com/_ah/api#p/
"""
import calendar
import datetime
import json
import sys
import urllib
import urllib2

BUILDER_LIST_URL = ('https://chrome-infra-stats.appspot.com/'
                    '_ah/api/stats/v1/masters/chromium.perf')

BUILDER_STATS_URL = ('https://chrome-infra-stats.appspot.com/_ah/api/stats/v1/'
                     'stats/chromium.perf/%s/overall__build__result__/%s')

USAGE = ('Usage: chrome_perf_stats.py <year> <month> <day>. If date is not '
         'specified, yesterday will be used.')

def main():
  if len(sys.argv) == 2 and sys.argv[0] == '--help':
    print USAGE
    sys.exit(0)
  year = None
  month = None
  days = None
  if len(sys.argv) == 4 or len(sys.argv) == 3:
    year = int(sys.argv[1])
    if year > 2016 or year < 2014:
      print USAGE
      sys.exit(0)
    month = int(sys.argv[2])
    if month > 12 or month <= 0:
      print USAGE
      sys.exit(0)
    if len(sys.argv) == 3:
      days = range(1, calendar.monthrange(year, month)[1] + 1)
    else:
      day = int(sys.argv[3])
      if day > 31 or day <=0:
        print USAGE
        sys.exit(0)
      days = [day]
  elif len(sys.argv) != 1:
    print USAGE
    sys.exit(0)
  else:
    yesterday = datetime.date.today() - datetime.timedelta(days=1)
    year = yesterday.year
    month = yesterday.month
    days = [yesterday.day]

  response = urllib2.urlopen(BUILDER_LIST_URL)
  builders = [builder['name'] for builder in json.load(response)['builders']]
  success_rates = CalculateSuccessRates(year, month, days, builders)
  UploadToPerfDashboard(success_rates)

def _UpdateSuccessRatesWithResult(
    success_rates, results, date_dict_str, builder):
  count = int(results['count'])
  if count == 0:
    return
  success_count = count - int(results['failure_count'])
  success_rates.setdefault(date_dict_str, {})
  success_rates[date_dict_str].setdefault(builder, {
      'count': 0,
      'success_count': 0
  })
  success_rates[date_dict_str][builder]['count'] += count
  success_rates[date_dict_str][builder]['success_count'] += success_count

def _SummarizeSuccessRates(success_rates):
  overall_success_rates = []
  for day, results in success_rates.iteritems():
    success_rate_sum = 0
    success_rate_count = 0
    for builder, rates in results.iteritems():
      if rates['count'] == 0:
        continue
      success_rate_sum += (
          float(rates['success_count']) / float(rates['count']))
      success_rate_count += 1
    overall_success_rates.append(
        [day, float(success_rate_sum) / float(success_rate_count)])
  return overall_success_rates

def UploadToPerfDashboard(success_rates):
  for success_rate in success_rates:
    date_str = ('%s-%s-%s' %
        (success_rate[0][0:4], success_rate[0][4:6], success_rate[0][6:8]))
    dashboard_data = {
        'master': 'WaterfallStats',
        'bot': 'ChromiumPerf',
        'point_id': int(success_rate[0]),
        'supplemental': {},
        'versions': {
            'date': date_str,
        },
        'chart_data': {
            'benchmark_name': 'success_rate',
            'benchmark_description': 'Success rates averaged per-builder',
            'format_version': 1.0,
            'charts': {
                'overall_success_rate': {
                    'summary': {
                        'name': 'overall_success_rate',
                        'type': 'scalar',
                        'units': '%',
                        'value': success_rate[1]
                    }
                }
            }
        }
    }
    url = 'https://chromeperf.appspot.com/add_point'
    data = urllib.urlencode({'data': json.dumps(dashboard_data)})
    content = urllib2.urlopen(url=url, data=data).read()


def CalculateSuccessRates(year, month, days, builders):
  success_rates = {}
  for day in days:
    for hour in range(24):
      date_str = '%d-%02d-%02dT%02d:00Z' % (year, month, day, hour)
      date_dict_str = '%d%02d%02d' % (year, month, day)
      for builder in builders:
        url = BUILDER_STATS_URL % (
            urllib.quote(builder), urllib.quote(date_str))
        response = urllib2.urlopen(url)
        results = json.load(response)
        _UpdateSuccessRatesWithResult(
            success_rates, results, date_dict_str, builder)
  return _SummarizeSuccessRates(success_rates)


if __name__ == "__main__":
  main()